package com.ljx.flyWeight;

import lombok.Data;

import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 享元模式
 *
 * 应用场景：
 * 当系统中多处需要同一组信息时，可以吧这些信息封装到一个对象中，然后对该对象进行缓存，这样，一个对象就可以提供给多处需要使用的地方，避免大量同一对象多次创建，消耗大量内存空间。
 * 享元模式其实就是工厂模式的一个改进机制，享元模式同样要求创建一个或一组对象，并且就是通过工厂方法生成对象的，只不过享元模式中为工厂方法增加了缓存这一功能。主要总结为以下应用场景：
 * 1、常常应用于系统底层的开发，以便解决系统的性能问题。
 * 2、系统有大量相似的对象、需要缓存池的场景。
 * 在生活中的享元模式也很常见，比如中介机构的房源共享，再比如全国社保联网。
 *
 * 优点：
 * 1、减少对象的创建 ，降低内存中对象的数量 ，降低系统的内存 ，提高效率；
 * 2、减少内存之外的其它资源占用。
 * 缺点：
 * 1、关注内、外部状态、关注线程安全问题；
 * 2、使系统、程序复杂化。
 *
 *
 * 经典案例：
 * JDK String 当以字面量形式创建字符串对象时，JVM会在编译期将其放到字符串常量池中，在Java启动时就加载到内存中了，这些字符串常量有且只有一份
 * JDK Integer -128~127之间范围内的整数，都是直接从缓存中取出，而非创建一个新的对象。如此可以大大节省内存空间
 *
 * @作者 LJX
 * @日期 2022/12/20 17:04
 */
public class FlyWeightTest {

    public static void main(String[] args) {
        TreeNode treeNode1 = new TreeNode(12, 12, TreeFactory.getTree("第一个树", "XXX"));
        TreeNode treeNode2 = new TreeNode(122, 122, TreeFactory.getTree("第一个树", "XXX"));
        TreeNode treeNode3 = new TreeNode(1222, 1222, TreeFactory.getTree("第二个树", "XXXYYY"));
        TreeNode treeNode4 = new TreeNode(12222, 12222, TreeFactory.getTree("第二个树", "XXXYYY"));
    }

}


@Data
class TreeNode{
    private Integer x;
    private Integer y;
    private Tree tree;

    public TreeNode(Integer x, Integer y, Tree tree) {
        this.x = x;
        this.y = y;
        this.tree = tree;
    }
}

@Data
class Tree{
    private String name;
    private String data;

    public Tree(String name, String data) {
        System.out.println("创建-----树名称："+name);
        this.name = name;
        this.data = data;
    }
}

/**
 * 享元工厂
 */
class TreeFactory{

    static Map<String, Tree> map = new ConcurrentHashMap();

    public static Tree getTree(String name, String data){
        if(map.containsKey(name)){
            return map.get(name);
        }
        Tree t = new Tree(name, data);
        map.put(name,t);
        return t;
    }

}
